const webpack = require('webpack');
const process = require('process');
const os = require('os');
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

const {port} = require('../config/index')
const {devtool, https, define: cDefine, progress, hmr}  = require('../config/index')
const {router, sendMsg} = require('./utils')
const {version} = require('../package.json')
const mode = (process.env.npm_lifecycle_script || '').includes(
  '--mode=development',
)
  ? 'development'
  : 'production';
const isBuild = !(process.env.npm_lifecycle_script || '').includes('server')
const devMode = mode === 'development';
const wsPath = '/ws_' + Date.now();

const define = {
  'process.env.NODE': JSON.stringify(mode),
  'process.env.NODE_ENV': JSON.stringify(mode),
  'process.env._build': JSON.stringify(isBuild),
}
Object.keys(cDefine).forEach(key => {
  define[key] = JSON.stringify(cDefine[key])
})

//  未开启 css module 的 loader
const cssLoader = [
  'style-loader',
  'css-loader',
  {
    loader: 'less-loader',
    options: {
      lessOptions: {
        javascriptEnabled: true,
      },
    },
  },
];
// 开启 css module 的 loader
const cssModulesLoader = JSON.parse(JSON.stringify(cssLoader));
cssModulesLoader[1] = {
  loader: 'css-loader',
  options: {
    modules: {
      localIdentName: '[local]_[hash:base64:5]',
    },
  },
};

const base = {
  mode: mode,
  devtool: devMode ? 'source-map' : devtool || false,
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  output: {
    clean: true,
    publicPath: 'auto',
    chunkFilename: version + '_[id]_[contenthash].js',
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: [
          {
            loader: 'thread-loader',
            options: {
              workers: 2,
              workerParallelJobs: 50,
              workerNodeArgs: ['--max-old-space-size=1024'],
            },
          },
          {
            // 采用babel-loader 才能支持 css module auto
            loader: require.resolve('babel-loader'),
            options: {
              babelrc: false,
              presets: [
                [
                  require.resolve('@umijs/babel-preset-umi'),
                  {
                    presetEnv: {
                      targets: [
                        "last 2 versions",
                        "Firefox ESR",
                        "> 1%",
                        "ie > 11"
                      ]
                    },
                    presetReact: {},
                    presetTypeScript: {},
                    pluginTransformRuntime: {},
                    pluginLockCoreJS: {},
                    pluginDynamicImportNode: false,
                    pluginAutoCSSModules: true,
                  },
                ],
              ],
            },
          },
        ],
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.less$/,
        oneOf: [
          {
            resourceQuery: /\?modules$/, // 只要匹配到了这个，就是用css modules，
            use: cssModulesLoader.filter(Boolean),
          },
          {
            use: cssLoader.filter(Boolean),
          },
        ],
      },
      {
        test: /\.(png|jpeg|jpg|svg|webp|gif|woff2|woff|ttf|eot)$/,
        type: 'asset',
      },
    ],
  },
  devServer: {
    https,
    hot: hmr,
    /** webpack dev server 高版本需要开始 */
    historyApiFallback: true,
    allowedHosts: 'all',
    setupMiddlewares: (middlewares, devServer) => {
      devServer.compiler.hooks.done.tap('console', () => {
        const msg = [];
        const name = devServer.options.port == port.basic ? '公共库' : '组件库';
        msg.push(`【${name}】 ` + '调试链接地址：' + getIP().map(ip => `http${devServer.server.cert ? 's' : ''}://${ip}:${devServer.options.port}/`).join(' 或 '))
        if (devServer.server.cert) {
          msg.push(`【${name}】 https模型下，首次使用时请先访问 ` +  getIP().map(ip => `http${devServer.server.cert ? 's' : ''}://${ip}:${devServer.options.port}/https.html`).join(' 或 ') + ' 获得跨域授权')
        }
        sendMsg({
          port: devServer.options.port === port.basic ? port.component : port.basic,
          isHttps: devServer.server.cert,
          msg:msg
        })

        setTimeout(() => {
          msg.forEach(item => {
            console.log(item)
          });
          if (global._webpackConsole) {
            global._webpackConsole.forEach(item => {
              console.log(item)
            })
          }
        }, 100);
      });
      router(devServer.app, devServer);
      return middlewares;
    },
    client: hmr ? {
      overlay: false,
      //reconnect: 3,
      webSocketURL: {
        hostname: '127.0.0.1',
        pathname: wsPath
      },
    }: false,
    webSocketServer: {
      options: {
        path: wsPath
      }
    }
  },
  plugins: [
    new webpack.DefinePlugin(define),
    new webpack.ProvidePlugin({
      InbizConfig: 'InbizConfig',
    }),
    progress && new webpack.ProgressPlugin({
      activeModules: true,         // 默认false，显示活动模块计数和一个活动模块正在进行消息。
      modules: false,              // 默认true，显示正在进行的模块计数消息。
      dependencies: false,         // 默认true，显示正在进行的依赖项计数消息。
    }),
    isBuild && new CompressionWebpackPlugin({
      // filename: 文件名称，这里不设置，让他保持和未压缩的文件同一个名称
      algorithm: 'gzip', // 指定生成gzip格式
      test: productionGzipExtensions, // 匹配对于格式文件进行压缩
      threshold: 10240, // 对超过10k的数据进行压缩
      minRatio: 0.6, // 压缩比例，值为0~1
    })
  ].filter(item => !!item),
};

function getIP() {
  const interfaces = os.networkInterfaces();
  return Object.values(interfaces).flat().filter(item => {
      return item.family === 'IPv4' && item.address !== '127.0.0.1' && !item.internal
  }).map(item => item.address);
}

// 公共配置
exports.base = base;




const basic = {
  react: 'inbizPluginInterface["React"]',
  React: 'inbizPluginInterface["React"]',
  'react-dom': 'inbizPluginInterface["ReactDOM"]',
  'react-router-dom': 'inbizPluginInterface["ReactRouterDOM"]',
  '@formily/core': 'inbizPluginInterface["formily_core"]',
  '@formily/react': 'inbizPluginInterface["formily_react"]',
  '@inbiz/core': 'inbizPluginInterface["inbiz_core"]',
  '@inbiz/react': 'inbizPluginInterface["inbiz_react"]',
  '@formily/reactive': 'inbizPluginInterface["formily_reactive"]',
  lodash: 'inbizPluginInterface["lodash"]',
  ahooks: 'inbizPluginInterface["ahooks"]',
  '@inbiz/core': 'inbizPluginInterface["inbiz_core"]',
  moment: 'inbizPluginInterface["moment"]',
  '@editor': 'inbizPluginInterface["editor"]',
  '@inbiz/react-settings-form': 'inbizPluginInterface["react-settings-form"]',
  InbizConfig: 'inbizPluginInterface["InbizConfig"]',
  antd: 'inbizPluginInterface["antd"]',
  '@inbiz/antd': 'inbizPluginInterface["antd"]',
  'react/jsx-runtime': 'inbizPluginInterface["jsx_runtime"]',
  'antd-mobile': 'inbizPluginInterface["antdMobile"]',
};

const packages = [
  '@inbiz/componentsWeb',
  '@inbiz/componentsWap',
  '@inbiz/previewComponents',
  '@inbiz/hooks',
  '@inbiz/utils',
  '@inbiz/render',
  '@inbiz/setters'
];
const senior = [
  basic,
  ({ request }, callback) => {
    if (packages.includes(request) || request.includes('@inbiz/basic')) {
      callback(null, 'promise _importInbiz_("' + request + '")');
    } else {
      callback();
    }
  },
];

exports.basic = basic;
exports.senior = senior;

exports.options = {
  isBuild
}